/*
* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

use ohmw_dora::server::DoraServer;

pub struct MWServer {
    kind: MWServerKind,
}

#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum MWServerKind {
    Dora,
    ROS,
    ROS2,
}

#[derive(Debug, thiserror::Error)]
pub enum MWServerError {
    #[error("Launch failed")]
    LaunchFailed,
    #[error(transparent)]
    DoraError(#[from] eyre::Error),
}

impl MWServer {
    pub fn new(kind: MWServerKind) -> Result<Self, MWServerError> {
        match kind {
            MWServerKind::Dora => {
                let server = Self { kind };
                if !DoraServer::is_running() {
                    server.launch_ohmw_server()?;
                }
                Ok(server)
            },
            MWServerKind::ROS => todo!(),
            MWServerKind::ROS2 => todo!(),
        }
    }

    pub fn start(&mut self) -> Result<(), MWServerError> {
        match self.kind {
            MWServerKind::Dora => {
                if !DoraServer::is_running() {
                    self.launch_ohmw_server()?;
                }
                Ok(())
            },
            MWServerKind::ROS => todo!(),
            MWServerKind::ROS2 => todo!(),
        }
    }

    pub fn stop(&mut self) -> Result<(), MWServerError> {
        match self.kind {
            MWServerKind::Dora => {
                DoraServer::stop()?;
                Ok(())
            },
            MWServerKind::ROS => todo!(),
            MWServerKind::ROS2 => todo!(),
        }
    }

    pub fn is_running(kind: MWServerKind) -> bool {
        match kind {
            MWServerKind::Dora => DoraServer::is_running(),
            MWServerKind::ROS => todo!(),
            MWServerKind::ROS2 => todo!(),
        }
    }

    fn launch_ohmw_server(&self) -> Result<(), MWServerError> {
        #[cfg(not(feature = "no-sa"))]
        if unsafe { sa::launch_ohmw_server(self.kind) } != 0 {
            return Err(MWServerError::LaunchFailed);
        }
        Ok(())
    }
}

#[cfg(not(feature = "no-sa"))]
mod sa {
    use crate::mw_server::MWServerKind;

    unsafe extern "C" {
        pub fn launch_ohmw_server(kind: MWServerKind) -> i32;
    }
}
